﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using TTGame;
using System.Diagnostics;
using System;

/*
 * DebugTime
 * 分析游戏耗时
 *
 *
 * 依赖：
 *
 * ！不写重复代码！
 * @author TTun
 * @date 7/28/2017 9:09:01 AM
 */
namespace TTGameEngine {

public class TimeWatcher {
    public uint id;
    public string tag;
    public Stopwatch sw;
    public string startMsg;
    public string endMsg;
    public int FrameCount = 0;
    public double timeResult = 0f;


    public void Reset() {
        tag = "";
        sw = null;
        startMsg = "";
        endMsg = "";
        FrameCount = 0;
        timeResult = 0f;
    }

    public string GetDumpStr() {
        return string.Format("[{0}]\ttime[{1}s]\tframe[{2}] msg:{3} / {4}", id, timeResult, FrameCount, startMsg, endMsg);
    }
}

public class DebugTime {
    static DebugTime _ins = new DebugTime();
    public static bool Enable = true;
    public static bool logMsgImm = false;
    public static DebugTime Ins {
        get {return _ins;}
    }
    //为了防止log增加耗时，影响分析，先记录最后再打印整体log。
    public bool IsSilence;

    const int InitStopwatchCount = 10;
    public Stack<Stopwatch> freeStopwatchs = new Stack<Stopwatch>();
    //public Dictionary<string, TimeWatcher> watchers = new Dictionary<string, TimeWatcher>();
    public List<TimeWatcher> watchers = new List<TimeWatcher>();
    public List<TimeWatcher> runningWatchers = new List<TimeWatcher>();
    CountID_UInt globalID = new CountID_UInt();

    public const uint DefaultGID = uint.MaxValue;

    DebugTime() {
        init();
    }

    void init() {
        for(int i = 0; i < InitStopwatchCount; i++) {
            freeStopwatchs.Push(new Stopwatch());
        }
        appedListNull(watchers, 20);
    }

    Stopwatch ObtainStopwatch() {
        if(freeStopwatchs.Count > 0) {
            return freeStopwatchs.Pop();
        } else {
            return new Stopwatch();
        }
    }

    void appedListNull<T>(List<T> list, int num) {
        for(int i = 0; i < num; i++) {
            list.Add(default(T));
        }
    }

    TimeWatcher ObtainTimeItem(uint id = 0) {
        TimeWatcher watcher = null;
//         if(watchers.TryGetValue(tag, out watcher) == false) {
//             watcher = new TimeWatcher();
//             watcher.tag = tag;
//             watchers.Add(tag, watcher);
//         }
        if(id <= 0 || id >= watchers.Count) {
            appedListNull(watchers, 10);
            watcher = new TimeWatcher();
            watcher.id = globalID.GetGID();
            watchers[(int)watcher.id] = watcher;
        } else {
            watcher = watchers[(int)id];
        }
        return watcher;
    }

    void BackStopwatch(Stopwatch sw) {
        sw.Reset();
        freeStopwatchs.Push(sw);
    }

    public uint StartCheckPoint(string msg = "") {
        if(Enable == false) return 0;
        if (logMsgImm) DebugUtil.Log(msg);
        Stopwatch sw = ObtainStopwatch();
        TimeWatcher watcher = ObtainTimeItem();
        runningWatchers.Add(watcher);
        watcher.sw = sw;
        watcher.startMsg = msg;
        sw.Start();
        return watcher.id;
    }

    public void EndCheckPoint(uint id, string msg = "") {
        if(Enable == false) return;

        TimeWatcher watcher = ObtainTimeItem(id);

        watcher.endMsg = msg;
        watcher.timeResult = (double)watcher.sw.ElapsedMilliseconds / 1000;
        BackStopwatch(watcher.sw);
        watcher.sw = null;
        runningWatchers.Remove(watcher);

    }

    public void CountUpdate() {
        if(Enable == false) return;

        for(int i = 0; i < runningWatchers.Count; i++) {
            runningWatchers[i].FrameCount++;
        }
    }

    public void Dump() {
        if(Enable == false) return;

        string log = "*** 耗时统计LOG ***\n";
        foreach(TimeWatcher watcher in watchers) {
            if(watcher != null) {
                log += watcher.GetDumpStr();
                log += "\n";
            }
        }
        log += string.Format("还有正在运行的Watcher{0}个", runningWatchers.Count);
        DebugUtil.Log(log);
    }
}
}
